﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Linq;
using MvvmCodeReduction.Helpers;
using MvvmCodeReduction.Model;

namespace MvvmCodeReduction.View.CodeBehind
{
    /// <summary>
    /// Interaction logic for CustomersCodeBehind.xaml
    /// </summary>
    public partial class CustomersCodeBehind : Window
    {
        private readonly IRepository _repository;
        private const string _cancel = "Cancel";
        private const string _edit = "Edit";
        private IEnumerable<Model.Customer> _customers;

        public CustomersCodeBehind(IRepository repository)
        {
            _repository = repository;
            _customers = _repository.GetCustomers();
            DataContext = _customers;
            InitializeComponent();
        }

        #region Event Handlers

        private void EditButton_Click(object sender,
                                      RoutedEventArgs e)
        {
            // Get controls
            var frameworkElement = sender as FrameworkElement;
            if (frameworkElement == null)
            {
                Alert(
                    "Unable to cast sender to FrameworkElement.");
                return;
            }
            Customer customer =
                frameworkElement.DataContext as Customer;
            if (customer == null)
            {
                Alert(
                    "Unable to retrieve customer from DataContext.");
                return;
            }
            Button editButton =
                GetItemChildByCustomer<Button>(customer,
                                               "EditButton");
            if (editButton == null)
            {
                Alert("Unable to get EditButton.");
                return;
            }
            Button saveButton =
                GetItemChildByCustomer<Button>(customer,
                                               "SaveButton");
            if (saveButton == null)
            {
                Alert("Unable to get saveButton.");
                return;
            }
            TextBlock nameTextBlock =
                GetItemChildByCustomer<TextBlock>(customer,
                                                  "NameTextBlock");
            if (nameTextBlock == null)
            {
                Alert("Unable to get nameTextBlock.");
                return;
            }
            TextBox editTextBox =
                GetItemChildByCustomer<TextBox>(customer,
                                                "EditTextBox");
            if (editTextBox == null)
            {
                Alert("Unable to get editTextBox.");
                return;
            }

            // Update state
            if (nameTextBlock.Visibility == Visibility.Visible)
            {
                nameTextBlock.Visibility = Visibility.Collapsed;
                editTextBox.Visibility = Visibility.Visible;
                editTextBox.Text = customer.Name;
                editButton.Content = _cancel;
                saveButton.IsEnabled = true;
            }
            else
            {
                nameTextBlock.Visibility = Visibility.Visible;
                editTextBox.Visibility = Visibility.Collapsed;
                editButton.Content = _edit;
                saveButton.IsEnabled = false;
            }
        }

        private void SaveButton_Click(object sender,
                                      RoutedEventArgs e)
        {
            // Get controls
            var frameworkElement = sender as FrameworkElement;
            if (frameworkElement == null)
            {
                Alert(
                    "Unable to cast sender to FrameworkElement.");
                return;
            }
            Customer customer =
                frameworkElement.DataContext as Customer;
            if (customer == null)
            {
                Alert(
                    "Unable to retrieve customer from DataContext.");
                return;
            }

            Button editButton =
                GetItemChildByCustomer<Button>(customer,
                                               "EditButton");
            if (editButton == null)
            {
                Alert("Unable to get EditButton.");
                return;
            }
            Button saveButton =
                GetItemChildByCustomer<Button>(customer,
                                               "SaveButton");
            if (saveButton == null)
            {
                Alert("Unable to get saveButton.");
                return;
            }
            TextBlock nameTextBlock =
                GetItemChildByCustomer<TextBlock>(customer,
                                                  "NameTextBlock");
            if (nameTextBlock == null)
            {
                Alert("Unable to get nameTextBlock.");
                return;
            }
            TextBox editTextBox =
                GetItemChildByCustomer<TextBox>(customer,
                                                "EditTextBox");
            if (editTextBox == null)
            {
                Alert("Unable to get editTextBox.");
                return;
            }

            if (nameTextBlock.Visibility == Visibility.Visible)
            {
                return;
            }

            saveButton.IsEnabled = false;
            customer.Name = editTextBox.Text;
            nameTextBlock.Text = editTextBox.Text;
            editButton.Content = string.Empty;
            nameTextBlock.Visibility = Visibility.Visible;
            editTextBox.Visibility = Visibility.Collapsed;
            editButton.Content = _edit;
        }

        #endregion Event Handlers

        #region Helpers

        private T GetItemChildByCustomer<T>(Customer customer,
                                            string buttonName)
            where T : FrameworkElement
        {
            ContentPresenter contentPresenter =
                CustomersItemsControl.ItemContainerGenerator.
                    ContainerFromItem(customer)
                as ContentPresenter;
            if (contentPresenter == null)
            {
                Alert("Unable to get ContentPresenter for Customer : " 
                    + customer.ID);
                return default(T);
            }
            IEnumerable<T> controls = UIHelpers.FindVisualChildren<T>(contentPresenter);
            if (controls == null)
            {
                Alert(
                    "Unable to retrieve " + typeof(T) 
                    + " from DataContext.");
                return default(T);
            }
            return
                controls.FirstOrDefault(b => b.Name == buttonName);
        }

        private void Alert(string message)
        {
            MessageBox.Show(message);
        }

        #endregion Helpers
    }
}
